package com.tonghl.juc.CAS_study.code;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * Created by tonghl
 *
 * static关键字：
 *
 * ABA问题的解决，AtomicStampedReference
 */
public class ABADemo {

    static AtomicReference atomicReference=new AtomicReference(100);

    static AtomicStampedReference atomicStampedReference=new AtomicStampedReference(100,1);

    //延时方法
    private static void sleep(long timeout){
        try{ TimeUnit.SECONDS.sleep(timeout);
            System.out.println("我先暂停"+timeout+"秒钟");}catch (InterruptedException e){e.printStackTrace();}
    }

    public static void main(String[] args) {

        new Thread(()->{
            atomicReference.compareAndSet(100,101);
            atomicReference.compareAndSet(101,100);
        },"T1").start();


        new Thread(()->{
            //T2线程先暂停1秒保证T1线程完成一次ABA的问题
             sleep(1);
            System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());
        },"T2").start();

        sleep(3);
        System.out.println("=====================以下是ABA问题的解决========================");

        new Thread(()->{
            int stamp=atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t第一次的版本号"+stamp);

            sleep(1);
            atomicStampedReference.compareAndSet(100,101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t第二次的版本号"+stamp);

            atomicStampedReference.compareAndSet(101,100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t第三次的版本号"+stamp);
        },"T3").start();

        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t第一次的版本号"+stamp);
            //暂停1秒中,保证T3线程完成一次ABA问题。
            sleep(1);
            boolean result = atomicStampedReference.compareAndSet(100, 2019, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName()+"\t修改是否成功："+result+" 当前实际最新版本号："+atomicStampedReference.getStamp());
            System.out.println("当前实际最新值："+atomicStampedReference.getReference());
        },"T4").start();
    }
}
